package com.cskaoyan.javase.oop2._1extends._9override._0introduction;

/**
 * 方法的覆盖
 * 父子类中的成员方法也是可以同名的。
 * 那么我们直接创建子类对象，使用子类引用接收。
 * 调用同名方法，会体现出子类的行为。
 *
 * 这时在父类中写一个同名方法的调用，再次调用该方法，发现仍然体现子类的行为
 * 这就是方法的覆盖，这是"对象名点成员方法"的调用机制决定的,决定了方法的覆盖
 * 注意: 方法的覆盖只是方法调用的机制决定的,不是真的物理意义上的覆盖了
 *      父类中的同名成员方法,在子类中,仍然可以用super.访问
 *
 * 研究"对象名点成员方法"的调用机制,还是三种创建对象的方式:
 *      1.子类引用指向子类对象
 *      2.父类引用指向父类对象
 *      3.父类引用指向子类对象
 * 研究"对象名点成员方法"的调用机制,仍然从两个角度:
 *      1.访问范围
 *          终究是一个编译上的概念,所以还是只需要看引用即可
 *          引用是父类类型,可以看父类
 *          引用是子类类型,可以看父类 + 子类
 *          只能往上找,不能往下找
 *
 *      2.调用的结果
 *          不能再看引用的类型中的方法了
 *          而是要看具体对象的类型中的方法实现
 *
 *
 * 以上,"对象名点成员方法":
 *      1.访问范围仍然看引用的类型
 *      2.调用的结果,就不再看引用了
 *          要根据具体的对象,来决定方法调用的结果.
 *
 *
 * @since 09:57
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Son s = new Son();
        s.test();
        s.invokeFatherTest();
        s.superInvokeFatherTest();*/

        // 1.子类引用指向子类对象
        Son s = new Son();
        // s.fatherTest();
        s.test();


        // 2.父类引用指向父类对象
        Father f = new Father();
        // f.fatherTest();
        f.test();

        // 3.父类引用指向子类对象
        Father fs = new Son();
        fs.test();
        // fs.sonTest();
    }
}

class Father {
    public void test() {
        System.out.println("Father");
    }

    public void fatherTest(){
        System.out.println("Father only");
    }

    // public void invokeFatherTest(){
    //     test();
    // }
}

class Son extends Father {
    public void test() {
        System.out.println("Son");
    }

    public void sonTest(){
        System.out.println("Son only");
    }

    // public void superInvokeFatherTest(){
    //     super.test();
    // }

}
